package com.hevs.samplewebapp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;

import com.hevs.samplewebapp.client.bean.JSONHelper;

/**
 * 
 * This is the entry point of the application
 * <p>The Goal is to provide the entry point of the application, 
 * it's where the onModuleLoad is called to build the whole application</p>
 * @author System
 * @date 12.03.12
 */
public class SampleModule implements EntryPoint {

	// ------------------------------------------------------------
	// VARIABLES
	// ------------------------------------------------------------

	// Graphical Elements

	/**
	 * Horizontal panel how contain the application
	 */
	private HorizontalPanel hp = new HorizontalPanel();

	/**
	 * Button for login
	 */
	private Button loginBtn = new Button("Login");

	/**
	 * TextBox to enter the login name
	 */
	private TextBox nameField = new TextBox();

	/**
	 * Textbox to enter the password
	 */
	private PasswordTextBox pwField = new PasswordTextBox();

	/**
	 * FlexTable how contains the different elements for the login
	 */
	private FlexTable ftLoginZone = new FlexTable();

	/**
	 * Button to log out of the application
	 */
	private Button btLogOut = new Button("Logout");

	/**
	 * Patient part of the application
	 * @see Patient
	 */
	private Patient patientWidget;

	/**
	 * Administrator part of the application
	 * @see Administration
	 */
	private Administration adminWidget;

	/**
	 * Doctor part of the application
	 * @see Doctor
	 */
	private Doctor docWidget;

	// URL
	/**
	 * Web service URL
	 * <p>URL to send and create a token to log in the application</p>
	 */
	private static final String JSON_URL_TOKEN = GWT.getModuleBaseURL()+"ws/security/token";

	// ----------------------------------------------------------------------------
	// Methods
	// ----------------------------------------------------------------------------

	/**
	 * Method how build the application, it's called when the user arrives on the web application
	 */
	public void onModuleLoad()
	{

		// set alignment in the panel
		hp.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);

		// default content and focus for username field
		nameField.setText("Username");

		// have to call those methods in a scheduler otherwise it wont work
		Scheduler.get().scheduleDeferred(new ScheduledCommand() {
			@Override
			public void execute() {
				// set focus on the name-field
				nameField.setFocus(true);
				// select whole text in the name-field
				nameField.selectAll();
			}
		});

		btLogOut.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				Window.Location.reload();				
			}
		});

		class MyHandler implements ClickHandler,KeyUpHandler
		{
			public void onClick(ClickEvent event)
			{
				sendNameToServer();
			}

			public void onKeyUp(KeyUpEvent event)
			{
				if(event.getNativeKeyCode()==KeyCodes.KEY_ENTER)
					sendNameToServer();
			}

			private void sendNameToServer()
			{
				// Validate input
				JSONObject login = new JSONObject();
				login.put("login", new JSONString(nameField.getText()));
				login.put("password", new JSONString(pwField.getText()));
				try {
					sendPOST(JSON_URL_TOKEN, login);
				} catch (Exception e) {
					e.printStackTrace();
				}

			}
		}

		// Add Handler to Buttons and Fields
		MyHandler handler=new MyHandler();
		loginBtn.addClickHandler(handler);
		nameField.addKeyUpHandler(handler);
		pwField.addKeyUpHandler(handler);

		// rows of the form
		ftLoginZone.setText(0, 0, "Please enter Username and Password : ");
		ftLoginZone.setWidget(1, 0, nameField);
		ftLoginZone.setWidget(2, 0, pwField);
		ftLoginZone.setWidget(3, 0, loginBtn);

		RootPanel.get("logout").add(btLogOut);
		hp.add(ftLoginZone);
		RootPanel.get("content").add(hp);
	}

	/**
	 * Method to send the login and password to the server then create the GUI in function of the credential level
	 * 
	 * @param url
	 *  The URL of the web service to login
	 * @param json
	 * 	the JSON object composed by login and password
	 * @throws Exception
	 * 	If the application cannot reach the server
	 */
	public void sendPOST(String url,JSONObject json) throws Exception
	{
		RequestBuilder builder=new RequestBuilder(RequestBuilder.POST,url);

		try
		{
			@SuppressWarnings("unused")
			Request response=builder.sendRequest(json.toString(),
					new RequestCallback()
			{
				public void onError(Request request,Throwable exception)
				{
					Window.alert("Error: could not reach host. Please check your connection and retry");
				}

				public void onResponseReceived(Request request,Response response)
				{
					if(response.getStatusCode() == 200){
						int levelOfUser = JSONHelper.asToken(response.getText()).getCredential();

						switch (levelOfUser) {
						case 3:
							// show administration widget
							adminWidget = new Administration();
							hp.clear();
							hp.add(adminWidget);
							break;

						case 2:
							// show doctor widget
							docWidget=new Doctor();
							hp.clear();
							hp.add(docWidget);
							break;

						case 1 :
							// show patient widget
							patientWidget = new Patient();
							hp.clear();
							hp.add(patientWidget);
							break;

						default:
							Window.Location.reload();
							break;
						}
					}
					else{
						Window.alert("Login failed, please retry");
					}
				}
			});
		}
		catch(RequestException e)
		{
			Window.alert("Login failed, please retry");
		}
	}
}